﻿/*
* 创建者：LIYINFAI
* 创建时间：2023/12/20 10:12:44
* 描述：SocketClientHelper
* --------------------------------------
* 修改说明：
* --------------------------------------
*/
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace CommonLibrary
{
    /// <summary>
    /// 套接字服务配置
    /// </summary>
    public class SocketServerConfig
    {
        /// <summary>
        /// Port
        /// </summary>
        [Description("Port")]
        public int Port { get; set; }
        /// <summary>
        /// MaxQueueCount
        /// </summary>
        [Description("MaxQueueCount")]
        public int MaxQueueCount { get; set; } = 20;
        /// <summary>
        /// ClientReceiveTimeout
        /// </summary>
        [Description("ClientReceiveTimeout")]
        public int ClientReceiveTimeout { get; set; } = 1000;
        /// <summary>
        /// ClientSendTimeout
        /// </summary>
        [Description("ClientSendTimeout")]
        public int ClientSendTimeout { get; set; } = 1000;

        /// <summary>
        /// 描述信息
        /// </summary>
        /// <returns></returns>

        public override string ToString()
        {
            return JsonConvert.SerializeObject(this, Formatting.None);
        }

    }
    /// <summary>
    /// 客户端接入代理
    /// </summary>
    /// <param name="ip"></param>
    /// <param name="port"></param>
    public delegate void AcceptDelegate(string ip, int port);
    /// <summary>
    /// 消息接收代理
    /// </summary>
    /// <param name="client"></param>
    /// <param name="data"></param>
    public delegate void ReceiveDelegate(Socket client, byte[] data);
    /// <summary>
    /// 套接字服务操作类
    /// </summary>
    public class SocketServerHelper
    {
        private List<Socket> mClients = new List<Socket>();
        private SocketServerConfig mConfig = null;
        private bool mIsRunning = true;
        private Socket mServer = null;

        /// <summary>
        /// 客户端接入代理
        /// </summary>
        public event AcceptDelegate Accept = null;
        /// <summary>
        /// 消息接收代理
        /// </summary>
        public event ReceiveDelegate Receive = null;
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="port"></param>
        public SocketServerHelper(int port) : this(new SocketServerConfig()
        {
            Port = port
        })
        {

        }
        private void AcceptClient()
        {
            while (this.mIsRunning)
            {
                try
                {
                    Socket client = this.mServer.Accept();
                    client.ReceiveTimeout = this.mConfig.ClientReceiveTimeout;
                    client.SendTimeout = this.mConfig.ClientSendTimeout;
                    this.mClients.Add(client);
                    IPEndPoint clientEndPoint = (client.RemoteEndPoint as IPEndPoint);
                    if (this.Accept != null)
                    {
                        this.Accept(clientEndPoint.Address.ToString(), clientEndPoint.Port);
                    }
                    ParameterizedThreadStart parameterizedThread = ReceiveClientMessage;
                    new Thread(parameterizedThread) { IsBackground = true }.Start(client);
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex, "", $"【AcceptClient】{this.mConfig}");
                }
            }
        }
        private void ReceiveClientMessage(object socket)
        {
            if (socket != null && socket is Socket)
            {
                Socket client = (Socket)socket;
                LogHelper.Info($"【Socket客户端连接】{client.RemoteEndPoint}");


                while (true)
                {
                    try
                    {
                        byte[] buffer = new byte[1024];
                        var poll = client.Poll(-1, SelectMode.SelectRead);
                        int len = client.Receive(buffer);
                        if (len <= 0)
                        {
                            break;
                        }
                        if (len > 0)
                        {
                            byte[] data = buffer.Take(len).ToArray();
                            LogHelper.Info($"【Socket收到客户端数据】{client.RemoteEndPoint} {string.Join(" ", data.Select(v => v.ToString("X2")))}");
                            if (this.Receive != null)
                            {
                                this.Receive(client, data);
                            }
                        }
                    }
                    catch
                    {
                    }
                }
                this.mClients.Remove(client);
                try
                {
                    LogHelper.Info($"【Socket关闭客户端】{client.RemoteEndPoint}");
                    client.Shutdown(SocketShutdown.Both);
                    client.Close();
                }
                catch (Exception ex1)
                {
                    LogHelper.Error(ex1, string.Empty, $"【Socket收到客户端数据】{client.RemoteEndPoint}");
                }
            }
        }
        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="client"></param>
        /// <param name="data"></param>
        public void SendData(Socket client, byte[] data)
        {
            if (client != null && data != null)
            {
                try
                {
                    LogHelper.Info($"【Socket往客户端发送数据】{client.RemoteEndPoint} {string.Join(" ", data.Select(v => v.ToString("X2")))}");
                    int len = client.Send(data);
                    LogHelper.Info($"【Socket往客户端发送数据】{client.RemoteEndPoint} 发送结果：{len == data.Length}");
                }
                catch (Exception ex)
                {
                    LogHelper.Error(ex, string.Empty, $"【Socket往客户端发送数据】{client.RemoteEndPoint}");
                }
            }
        }
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="config"></param>
        public SocketServerHelper(SocketServerConfig config)
        {
            try
            {
                if (config != null)
                {
                    this.mConfig = config;
                    this.mServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                    this.mServer.Bind(new IPEndPoint(IPAddress.Any, this.mConfig.Port));
                    this.mServer.Listen(this.mConfig.MaxQueueCount);
                    new Thread(AcceptClient) { IsBackground = true }.Start();
                    LogHelper.Info($"【Socket服务启动】{this.mConfig}");
                }
            }
            catch (Exception ex)
            {
                Close();
                LogHelper.Error(ex, "", $"【Socket服务启动】{config}");
            }
        }
        /// <summary>
        /// 析构函数
        /// </summary>
        ~SocketServerHelper()
        {
            this.Close();
        }
        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            try
            {
                this.mIsRunning = false;
                if (this.mServer != null && this.mServer.Connected)
                {
                    this.mServer.Close();
                    this.mServer = null;
                }
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex, "", $"【Socket服务停止】{this.mConfig}");
            }
            LogHelper.Info($"【Socket服务停止】{this.mConfig}");
        }
    }

}
